<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>平移旋转缩放矩阵</title>
    <style>
        body {
            margin: 0px;
            overflow: hidden;
        }

        #trsMatrix-Word {
            border: 3px solid blue;
            display: block;
        }

        #gui {
            position: absolute;
            left: 1020px;
            top: 10px;
        }
    </style>
</head>
<body>
    <canvas id="trsMatrix-Word" width="1000" height="800"></canvas>
    <div id="gui"></div>
    <script type="text/javascript" src="../libs/webgl-utils.js"></script>
    <script type="text/javascript" src="../libs/shader.js"></script>
    <script type="text/javascript" src="../libs/dat.gui.min.js"></script>

    <script id="v-shader" type="x-shader/x-vertex">
        attribute vec2 a_position;
        uniform vec2 u_resolution;
        uniform mat3 u_matrix;
        varying vec4 v_color;
        void main()
        {
            vec2 position = (u_matrix * vec3(a_position, 1.0)).xy;
            vec2 zeroToOne = position / u_resolution;
            vec2 clipSoace = zeroToOne * 2.0 - 1.0;

            gl_Position = vec4(clipSoace * vec2(1, -1), 0, 1);
            v_color = vec4(gl_Position.xyz * 0.5, 0.6);
        }
    </script>

    <script id="f-shader" type="x-shader/x-fragment">
        #ifdef GL_ES
        precision mediump float;
        #endif

        varying vec4 v_color;
        void main()
        {
            gl_FragColor = v_color.rgba;
        }
    </script>
    <script type="text/javascript">
        let translate = [100, 150];
        let angle = 0;
        let scale = [0.8, 0.8];

        //王
        let wang = [
            //第一横
            0, 0,
            150, 0,
            0, 30,
            0, 30,
            150, 0,
            150, 30,

            //第二横
            0, 80,
            150, 80,
            0, 110,
            0, 110,
            150, 80,
            150, 110,

            //第三横
            0, 160,
            150, 160,
            0, 190,
            0, 190,
            150, 160,
            150, 190,

            //竖
            60, 30,
            60, 160,
            90, 30,
            90, 30,
            60, 160,
            90, 160
        ];

        let guiField = {
            '平移X': translate[0],
            '平移Y': translate[1],
            '旋转角度': 0,
            '缩放X': scale[0],
            '缩放Y': scale[1]
        };

        let m3 = {
            identity: function() {
                return [
                    1, 0, 0,
                    0, 1, 0,
                    0, 0, 1
                ]
            },

            translation: function(tx, ty) {
                return [
                    1, 0, 0,
                    0, 1, 0,
                    tx, ty, 1
                ]
            },

            rotation: function(angle) {
                let c = Math.cos(angle);
                let s = Math.sin(angle);

                return [
                    c, -s, 0,
                    s, c, 0,
                    0, 0, 1
                ]
            },

            scaling: function(sx, sy) {
                return [
                    sx, 0, 0,
                    0, sy, 0,
                    0, 0, 1
                ]
            },

            multiply: function(a, b) {
                let a00 = a[0 * 3 + 0];
                let a01 = a[0 * 3 + 1];
                let a02 = a[0 * 3 + 2];
                let a10 = a[1 * 3 + 0];
                let a11 = a[1 * 3 + 1];
                let a12 = a[1 * 3 + 2];
                let a20 = a[2 * 3 + 0];
                let a21 = a[2 * 3 + 1];
                let a22 = a[2 * 3 + 2];
                let b00 = b[0 * 3 + 0];
                let b01 = b[0 * 3 + 1];
                let b02 = b[0 * 3 + 2];
                let b10 = b[1 * 3 + 0];
                let b11 = b[1 * 3 + 1];
                let b12 = b[1 * 3 + 2];
                let b20 = b[2 * 3 + 0];
                let b21 = b[2 * 3 + 1];
                let b22 = b[2 * 3 + 2];
                return [
                    b00 * a00 + b01 * a10 + b02 * a20,
                    b00 * a01 + b01 * a11 + b02 * a21,
                    b00 * a02 + b01 * a12 + b02 * a22,
                    b10 * a00 + b11 * a10 + b12 * a20,
                    b10 * a01 + b11 * a11 + b12 * a21,
                    b10 * a02 + b11 * a12 + b12 * a22,
                    b20 * a00 + b21 * a10 + b22 * a20,
                    b20 * a01 + b21 * a11 + b22 * a21,
                    b20 * a02 + b21 * a12 + b22 * a22,
                ];
            }
        };

        main();

        function main() {
            let canvas = document.getElementById('trsMatrix-Word');
            let gl = canvas.getContext('webgl', {antialias: true, depth: false});
            if(!gl) {
                alert("您的浏览器不支持WebGL!");
            }

            let vShaderSource = document.getElementById('v-shader').text;
            let fShaderSource = document.getElementById('f-shader').text;

            let program = initShader(gl, vShaderSource, fShaderSource);

            program.pLocation = getAttribute(gl, program, 'a_position');
            program.rLocation = getUniform(gl, program, 'u_resolution');
            program.mLocation = getUniform(gl, program, 'u_matrix');

            program.pBuffer = gl.createBuffer();
            gl.bindBuffer(gl.ARRAY_BUFFER, program.pBuffer);

            drawScene(gl, program);
            initGUI(gl, program);

        }

        //获取着色器中的attribute变量的位置
        function getAttribute(gl, program, name) {
            return gl.getAttribLocation(program, name);
        }

        //获取着色器中的uniform变量的位置
        function getUniform(gl, program, name) {
            return gl.getUniformLocation(program, name)
        }

        function initGUI(gl, program) {
            let gui = new dat.GUI();
            gui.add(guiField, '平移X', 0, gl.canvas.width-200).onChange(function(e) {
                translate[0] = e;
                drawScene(gl, program);
            });
            gui.add(guiField, '平移Y', 0, gl.canvas.height-200).onChange(function(e) {
                translate[1] = e;
                drawScene(gl, program);
            });

            gui.add(guiField, '旋转角度', -360, 360).onChange(function (e) {
                angle = e * Math.PI / 180;
                drawScene(gl, program);
            });

            gui.add(guiField, '缩放X', -4, 4).onChange(function (e) {
                scale[0] = e;
                drawScene(gl, program)
            });
            gui.add(guiField, '缩放Y', -4, 4).onChange(function (e) {
                scale[1] = e;
                drawScene(gl, program)
            });

            let ui = document.getElementById('gui');
            ui.appendChild(gui.domElement);
        }

        function drawScene(gl, program) {
            webglUtils.resizeCanvasToDisplaySize(gl.canvas);
            gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);

            gl.clearColor(0.0, 0.0, 0.0, 1.0);
            gl.clear(gl.COLOR_BUFFER_BIT);


            gl.useProgram(program);

            gl.enableVertexAttribArray(program.pLocation);

            gl.bindBuffer(gl.ARRAY_BUFFER, program.pBuffer);

            setGeometry(gl, wang);

            gl.vertexAttribPointer(program.pLocation, 2, gl.FLOAT, false, 0, 0);

            gl.uniform2f(program.rLocation, gl.canvas.width, gl.canvas.height);

            let tMatrix = m3.translation(translate[0], translate[1]);
            let rMatrix = m3.rotation(angle);
            let sMatrix = m3.scaling(scale[0], scale[1]);
            // let orignMatrix = m3.translation(-50, -75);//约束图形绕(-50, -75)点旋转
            var matrix = m3.identity();
            for (let i = 0; i < 8; i++) {
                matrix = m3.multiply(matrix, tMatrix);
                matrix = m3.multiply(matrix, rMatrix);
                matrix = m3.multiply(matrix, sMatrix);
                // matrix = m3.multiply(matrix, orignMatrix);
                gl.uniformMatrix3fv(program.mLocation, false, matrix);
                gl.drawArrays(gl.TRIANGLES, 0, wang.length / 2);
            }
        }

        function setGeometry(gl, array) {
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(array), gl.STATIC_DRAW);
        }

    </script>
</body>
</html>